package com.mi.rule.security.auth;

import com.mi.rule.security.resource.Res;
import com.mi.rule.security.resource.ResApi;
import com.mi.rule.util.ContextKit;
import com.mi.rule.util.EnvKit;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;

/**
 * --太搂了谁也别用.奥.
 * 资源处理器（用于扫描注解）
 */
public class AuthHandler {
    /**
     * 全部资源
     */
    private static HashMap<String, HashSet<String>> codeRes;

    public static HashMap<String, HashSet<String>> getCodeRes() {
        return AuthHandler.codeRes;
    }

    /**
     * 项目启动时
     * 调用此方法扫描系统中全部资源
     * ResourceHandler.getResList() 读取全部资源
     */
    public static synchronized void scan() {
        if (codeRes == null) {
            codeRes = new HashMap<>();

            //扫描所有具备Res资源注解的Class
            for (Object bean : ContextKit.getContext().getBeansWithAnnotation(Res.class).values()) {
                Class<?> aClass = bean.getClass();
                Method[] declaredMethods = aClass.getDeclaredMethods();
                Auth authController = AnnotationUtils.findAnnotation(aClass, Auth.class);
                RequestMapping controllerMapping = AnnotationUtils.findAnnotation(aClass, RequestMapping.class);
                if (controllerMapping == null) continue;

                //类上面有权限注解
                if (authController != null) {
                    handlingAnnotationsAboveClass(declaredMethods, authController, controllerMapping);
                    handlingAnnotationsAboveMethod(controllerMapping, declaredMethods);
                }

                //类上面没有权限注解
                if (authController == null) {
                    handlingAnnotationsAboveMethod(controllerMapping, declaredMethods);
                }

            }
        }

    }

    /**
     * 处理类之上的注解
     */
    private static void handlingAnnotationsAboveClass(Method[] declaredMethods, Auth authController, RequestMapping controllerMapping) {
        //遍历类注解上的所有Code
        for (String classCode : authController.value()) {
            HashSet<String> classResSet = codeRes.get(classCode);
            if (classResSet == null) {
                classResSet = new HashSet<>();
            }

            //遍历所有控制器
            for (String controllerValue : controllerMapping.value()) {
                String controllerPath = EnvKit.contextPath() + controllerValue;
                classResSet.add(controllerPath);

                //处理方法
                for (Method method : declaredMethods) {
                    ResApi resApi = AnnotationUtils.findAnnotation(method, ResApi.class);
                    RequestMapping methodMapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);
                    if (resApi == null || methodMapping == null) continue;

                    //遍历所有方法
                    for (String methodValue : methodMapping.value()) {
                        classResSet.add(controllerPath + methodValue);
                    }
                }

            }
            codeRes.put(classCode, classResSet);
        }
    }

    /**
     * 处理方法之上的注解
     */
    private static void handlingAnnotationsAboveMethod(RequestMapping controllerMapping, Method[] declaredMethods) {
        //遍历所有控制器
        for (String controllerValue : controllerMapping.value()) {
            String controllerPath = EnvKit.contextPath() + controllerValue;

            //遍历所有方法
            for (Method method : declaredMethods) {
                Auth authMethod = AnnotationUtils.findAnnotation(method, Auth.class);
                ResApi resApi = AnnotationUtils.findAnnotation(method, ResApi.class);
                RequestMapping methodMapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);

                if (resApi == null || authMethod == null || methodMapping == null) continue;

                for (String code : authMethod.value()) {
                    HashSet<String> resSet = codeRes.get(code);
                    if (resSet == null) {
                        resSet = new HashSet<>();
                    }
                    //遍历所有方法
                    for (String methodValue : methodMapping.value()) {
                        resSet.add(controllerPath + methodValue);
                    }
                    codeRes.put(code, resSet);
                }
            }

        }

    }


}
